package com.example.backend.repository.spec;

import com.example.backend.domain.entity.User;
import com.example.backend.domain.enums.Role;
import com.example.backend.domain.enums.UserStatus;
import com.example.backend.dto.UserFilter;
import org.springframework.data.jpa.domain.Specification;

import java.time.Instant;

/**
 * 用户查询规格构建器
 * 支持复杂的多条件查询，优化数据库查询性能
 */
public class UserSpecifications {

    /**
     * 根据筛选条件构建查询规格
     */
    public static Specification<User> withFilter(UserFilter filter) {
        if (filter == null) {
            // 默认过滤已删除的用户
            return isNotDeleted();
        }
        
        Specification<User> spec = isNotDeleted(); // 默认过滤已删除的用户
        
        // 基础条件
        spec = spec.and(hasRole(filter.getRole()));
        spec = spec.and(hasStatus(filter.getStatus()));
        spec = spec.and(hasDepartment(filter.getDepartment()));
        spec = spec.and(hasPosition(filter.getPosition()));
        
        // 时间范围条件
        spec = spec.and(createdFrom(filter.getCreatedFrom()));
        spec = spec.and(createdTo(filter.getCreatedTo()));
        spec = spec.and(lastLoginFrom(filter.getLastLoginFrom()));
        spec = spec.and(lastLoginTo(filter.getLastLoginTo()));
        
        // 文本搜索条件
        spec = spec.and(hasKeyword(filter.getKeyword()));
        spec = spec.and(hasUsernameKeyword(filter.getUsernameKeyword()));
        spec = spec.and(hasFullNameKeyword(filter.getFullNameKeyword()));
        spec = spec.and(hasEmailKeyword(filter.getEmailKeyword()));
        
        // 数值范围条件
        spec = spec.and(minLoginCount(filter.getMinLoginCount()));
        spec = spec.and(maxLoginCount(filter.getMaxLoginCount()));
        
        return spec;
    }

    // 基础条件规格
    public static Specification<User> hasRole(Role role) {
        return (root, query, cb) -> role == null ? cb.conjunction() : cb.equal(root.get("role"), role);
    }

    public static Specification<User> hasStatus(UserStatus status) {
        return (root, query, cb) -> status == null ? cb.conjunction() : cb.equal(root.get("status"), status);
    }

    public static Specification<User> hasDepartment(String department) {
        return (root, query, cb) -> department == null ? cb.conjunction() : cb.equal(root.get("department"), department);
    }

    public static Specification<User> hasPosition(String position) {
        return (root, query, cb) -> position == null ? cb.conjunction() : cb.equal(root.get("position"), position);
    }

    // 时间范围条件规格
    public static Specification<User> createdFrom(Instant from) {
        return (root, query, cb) -> from == null ? cb.conjunction() : cb.greaterThanOrEqualTo(root.get("createdAt"), from);
    }

    public static Specification<User> createdTo(Instant to) {
        return (root, query, cb) -> to == null ? cb.conjunction() : cb.lessThanOrEqualTo(root.get("createdAt"), to);
    }

    public static Specification<User> lastLoginFrom(Instant from) {
        return (root, query, cb) -> from == null ? cb.conjunction() : cb.greaterThanOrEqualTo(root.get("lastLoginAt"), from);
    }

    public static Specification<User> lastLoginTo(Instant to) {
        return (root, query, cb) -> to == null ? cb.conjunction() : cb.lessThanOrEqualTo(root.get("lastLoginAt"), to);
    }

    // 文本搜索条件规格
    public static Specification<User> hasKeyword(String keyword) {
        return (root, query, cb) -> {
            if (keyword == null || keyword.trim().isEmpty()) {
                return cb.conjunction();
            }
            String pattern = "%" + keyword.trim() + "%";
            return cb.or(
                cb.like(cb.lower(root.get("username")), pattern.toLowerCase()),
                cb.like(cb.lower(root.get("fullName")), pattern.toLowerCase()),
                cb.like(cb.lower(root.get("email")), pattern.toLowerCase())
            );
        };
    }

    public static Specification<User> hasUsernameKeyword(String keyword) {
        return (root, query, cb) -> {
            if (keyword == null || keyword.trim().isEmpty()) {
                return cb.conjunction();
            }
            String pattern = "%" + keyword.trim() + "%";
            return cb.like(cb.lower(root.get("username")), pattern.toLowerCase());
        };
    }

    public static Specification<User> hasFullNameKeyword(String keyword) {
        return (root, query, cb) -> {
            if (keyword == null || keyword.trim().isEmpty()) {
                return cb.conjunction();
            }
            String pattern = "%" + keyword.trim() + "%";
            return cb.like(cb.lower(root.get("fullName")), pattern.toLowerCase());
        };
    }

    public static Specification<User> hasEmailKeyword(String keyword) {
        return (root, query, cb) -> {
            if (keyword == null || keyword.trim().isEmpty()) {
                return cb.conjunction();
            }
            String pattern = "%" + keyword.trim() + "%";
            return cb.like(cb.lower(root.get("email")), pattern.toLowerCase());
        };
    }

    // 数值范围条件规格
    public static Specification<User> minLoginCount(Integer minCount) {
        return (root, query, cb) -> minCount == null ? cb.conjunction() : cb.greaterThanOrEqualTo(root.get("loginCount"), minCount);
    }

    public static Specification<User> maxLoginCount(Integer maxCount) {
        return (root, query, cb) -> maxCount == null ? cb.conjunction() : cb.lessThanOrEqualTo(root.get("loginCount"), maxCount);
    }

    // 复合条件规格
    public static Specification<User> hasRoleAndStatus(Role role, UserStatus status) {
        return hasRole(role).and(hasStatus(status));
    }

    public static Specification<User> hasDepartmentAndPosition(String department, String position) {
        return hasDepartment(department).and(hasPosition(position));
    }

    // 时间相关复合条件
    public static Specification<User> createdInRange(Instant from, Instant to) {
        return createdFrom(from).and(createdTo(to));
    }

    public static Specification<User> lastLoginInRange(Instant from, Instant to) {
        return lastLoginFrom(from).and(lastLoginTo(to));
    }

    // 活跃用户条件
    public static Specification<User> isActiveUser(Instant since) {
        return (root, query, cb) -> cb.greaterThanOrEqualTo(root.get("lastLoginAt"), since);
    }

    // 新用户条件
    public static Specification<User> isNewUser(Instant since) {
        return (root, query, cb) -> cb.greaterThanOrEqualTo(root.get("createdAt"), since);
    }
    
    // 未删除的用户条件（排除DELETED状态）
    public static Specification<User> isNotDeleted() {
        return (root, query, cb) -> cb.notEqual(root.get("status"), UserStatus.DELETED);
    }
}
